# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog
from qd import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt
import cv2
import numpy as np
import math


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        self.img_name = ''
        self.img_dst = 'img_dst.jpg'
        self.img_buff = 'img_buff.jpg'
        self.img_beaut = 'img_beaut.jpg'
        self.res_name = ''

        self.BLACK = 0
        self.GRAY = 1
        self.BLUR = 2
        self.OLD = 3
        self.FREEZE = 4
        self.MARBLE = 5
        self.HAHA1 = 6
        self.WAVE = 7

        self.img_filter = ['img_filter_black.jpg', 'img_filter_gray.jpg', 'img_filter_blur.jpg', 'img_filter_old.jpg',
                           'img_filter_freeze.jpg', 'img_filter_marble.jpg', 'img_filter_haha1.jpg',
                           'img_filter_wave.jpg']
        self.select_filter = 0
        self.state_filter = [-1] * len(self.img_filter)

        self.flag_img_open = False
        self.state_beauti = False
        self.state_buff = False
        self.value_beauti = 0
        self.value_buff = 0

    def bt_cf_click_open(self):
        self.img_name, filetype = QFileDialog.getOpenFileName(self, "选取文件", "./", "All Files (*);;")
        # 设置文件扩展名过滤,注意用双分号间隔
        if (self.img_name != ''):
            QPm_img = QPixmap(self.img_name)
            self.scrollAreaWidgetContents.resize(QPm_img.width(), QPm_img.height())
            self.label_pic.resize(QPm_img.width(), QPm_img.height())
            self.label_pic.setPixmap(QPm_img)
            self.flag_img_open = True
            for i in range(len(self.img_filter)):
                self.state_filter[i] = -1
            img = cv2.imread(self.img_name)  # 这四行代码得写，不然showPic在更换了源图片之后可能会出问题（beaut和buff双选框同时选上）
            cv2.imwrite(self.img_buff, img)
            cv2.imwrite(self.img_dst, img)
            cv2.imwrite(self.img_beaut, img)

    def bt_cf_click_save(self):
        file_path, filetype = QFileDialog.getSaveFileName(self, "保存文件", "./",
                                                          "jpg files (*.jpg);; png files (*.png);; all files(*.*)")
        img = cv2.imread(self.res_name)
        cv2.imwrite(file_path, img)

    def ck_filter_black(self, state):
        if not self.flag_img_open:
            return
        if (self.state_filter[self.BLACK] == -1):
            img_gray = cv2.imread(self.img_name, 0)
            ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
            cv2.imwrite(self.img_filter[self.BLACK], thresh)
        self.state_filter[self.BLACK] = int(state == Qt.Checked)
        if self.state_filter[self.BLACK]:
            self.select_filter = self.BLACK
            self.showPic(False)
        else:
            self.showPic()

    def ck_filter_gray(self, state):
        if not self.flag_img_open:
            return
        if (self.state_filter[self.GRAY] == -1):
            img_gray = cv2.imread(self.img_name, 0)
            cv2.imwrite(self.img_filter[self.GRAY], img_gray)
        self.state_filter[self.GRAY] = int(state == Qt.Checked)
        if self.state_filter[self.GRAY]:
            self.select_filter = self.GRAY
            self.showPic(False)
        else:
            self.showPic()

    def ck_filter_blur(self, state):
        if not self.flag_img_open:
            return
        if (self.state_filter[self.BLUR] == -1):
            img = cv2.imread(self.img_name, 1)
            ksize = 15
            temp = cv2.GaussianBlur(img, (ksize, ksize), 0)
            cv2.imwrite(self.img_filter[self.BLUR], temp)
        self.state_filter[self.BLUR] = int(state == Qt.Checked)
        if self.state_filter[self.BLUR]:
            self.select_filter = self.BLUR
            self.showPic(False)
        else:
            self.showPic()

    def ck_filter_old(self, state):
        if not self.flag_img_open:
            return
        if (self.state_filter[self.OLD] == -1):
            # 滤镜处理代码
            img = cv2.imread(self.img_name)
            row, col, height = img.shape
            for i in range(row):
                for j in range(col):
                    B = int(img[i][j][0])
                    G = int(img[i][j][1])
                    R = int(img[i][j][2])
                    b = 0.272 * R + 0.534 * G + 0.131 * B
                    g = 0.349 * R + 0.686 * G + 0.168 * B
                    r = 0.393 * R + 0.769 * G + 0.189 * B
                    if (b < 0): b = 0
                    if (b > 255): b = 255
                    if (g < 0): g = 0
                    if (g > 255): g = 255
                    if (r < 0): r = 0
                    if (r > 255): r = 255
                    img[i][j][0] = int(b)
                    img[i][j][1] = int(g)
                    img[i][j][2] = int(r)
            cv2.imwrite(self.img_filter[self.OLD], img)
        self.state_filter[self.OLD] = int(state == Qt.Checked)
        if self.state_filter[self.OLD]:
            self.select_filter = self.OLD
            self.showPic(False)
        else:
            self.showPic()

    def ck_filter_freeze(self, state):
        if not self.flag_img_open:
            return
        if (self.state_filter[self.FREEZE] == -1):
            # 滤镜处理代码
            img = cv2.imread(self.img_name)
            row, col, height = img.shape
            for i in range(row):
                for j in range(col):
                    B = int(img[i][j][0])
                    G = int(img[i][j][1])
                    R = int(img[i][j][2])
                    s = 0.8
                    b = (B - G - R) * s
                    g = (G - B - R) * s
                    r = (R - G - B) * s
                    r = (r > 255 and 255 or (r < 0 and -r or r))
                    g = (g > 255 and 255 or (g < 0 and -g or g))
                    b = (b > 255 and 255 or (b < 0 and -b or b))
                    img[i][j][0] = int(b)
                    img[i][j][1] = int(g)
                    img[i][j][2] = int(r)
            cv2.imwrite(self.img_filter[self.FREEZE], img)
        self.state_filter[self.FREEZE] = int(state == Qt.Checked)
        if self.state_filter[self.FREEZE]:
            self.select_filter = self.FREEZE
            self.showPic(False)
        else:
            self.showPic()

    def ck_filter_marble(self, state):
        if not self.flag_img_open:
            return
        if (self.state_filter[self.MARBLE] == -1):
            # 滤镜处理代码
            img = cv2.imread(self.img_name)
            row, col, height = img.shape
            dst = img.copy()
            for i in range(1, row - 1):
                for j in range(1, col - 1):
                    for k in range(3):
                        t = int(img[i + 1, j + 1, k]) - img[i, j - 1, k] + 128
                        if t < 0:
                            dst[i, j, k] = 0
                        elif t > 255:
                            dst[i, j, k] = 255
                        else:
                            dst[i, j, k] = t
            cv2.imwrite(self.img_filter[self.MARBLE], dst)
        self.state_filter[self.MARBLE] = int(state == Qt.Checked)
        if self.state_filter[self.MARBLE]:
            self.select_filter = self.MARBLE
            self.showPic(False)
        else:
            self.showPic()

    def ck_filter_haha1(self, state):
        if not self.flag_img_open:
            return
        if (self.state_filter[self.HAHA1] == -1):
            # 滤镜处理代码
            img = cv2.imread(self.img_name)
            dst = img.copy()
            row, col, height = img.shape
            x = int(row / 2)  # 255,255
            y = int(col / 2)
            R1 = x < y and x or y
            for i in range(row):
                for j in range(col):
                    dis = np.linalg.norm((i - x, j - y))
                    if dis < R1:
                        newi = int((i - x) * dis / R1 + x)
                        newj = int((j - y) * dis / R1 + y)
                        dst[i, j, :] = img[newi, newj, :]
            cv2.imwrite(self.img_filter[self.HAHA1], dst)
        self.state_filter[self.HAHA1] = int(state == Qt.Checked)
        if self.state_filter[self.HAHA1]:
            self.select_filter = self.HAHA1
            self.showPic(False)
        else:
            self.showPic()

    def ck_filter_wave(self, state):
        if not self.flag_img_open:
            return
        if (self.state_filter[self.WAVE] == -1):
            # 滤镜处理代码
            img = cv2.imread(self.img_name)
            dst = img.copy()
            row, col, rowt = img.shape
            angle = 0.0
            A = 10
            deltaI = 10.0
            for i in range(row):
                changej = int(A * math.sin(angle))
                for j in range(col):
                    if changej + j < col and changej + j > 0:  # 正弦分布（-1,1）
                        dst[i, j, :] = img[i, j + changej, :]
                    # 每行开始和结束的空白区
                    elif j <= changej:
                        dst[i, j, :] = img[i, 0, :]
                    elif j >= col - changej:
                        dst[i, j, :] = img[i, col - changej, :]
                angle += (float)(deltaI) / 100
            cv2.imwrite(self.img_filter[self.WAVE], dst)
        self.state_filter[self.WAVE] = int(state == Qt.Checked)
        if self.state_filter[self.WAVE]:
            self.select_filter = self.WAVE
            self.showPic(False)
        else:
            self.showPic()

    def beauti(self):
        img = cv2.imread(self.img_name)
        dst = cv2.addWeighted(img, 0.5, img, 0.5, self.value_beauti * 20)
        cv2.imwrite(self.img_beaut, dst)

    def buff(self):
        dx = self.value_buff * 3 + 5
        # dx = 25  # 25-28
        fc = 50  # 加上高斯模糊的时候较佳参数是9-75， 但如果图像有白色会出现异常
        # 双边滤波
        image = cv2.imread(self.img_name)
        temp1 = cv2.bilateralFilter(image, dx, fc, fc)
        # temp2 = (temp1 - image + 128)
        # # 高斯模糊
        # d = 3
        # temp3 = cv2.GaussianBlur(temp2, (d, d), 0, 0)
        # temp4 = image + 2 * temp3 - 255
        # p = 0.5  # 透明度
        # temp4 = cv2.addWeighted(image, 1 - p, temp4, p, 0)
        cv2.imwrite(self.img_buff, temp1)

    def spin_beau(self, value):
        self.value_beauti = value
        if self.flag_img_open and self.state_beauti:
            self.beauti()
            self.showPic()

    def spin_buff(self, value):
        self.value_buff = value
        if self.flag_img_open and self.state_buff:
            self.buff()
            self.showPic()

    def ck_beauti(self, state):
        self.state_beauti = (Qt.Checked == state)
        if not self.flag_img_open:
            return
        if self.state_beauti:
            self.beauti()
        self.showPic()

    def ck_buff(self, state):
        self.state_buff = (Qt.Checked == state)
        if not self.flag_img_open:
            return
        if self.state_buff:
            self.buff()
        self.showPic()

    def showPic(self, ifNotShowFilter=True):
        self.res_name = self.img_dst
        if ifNotShowFilter:
            if self.state_beauti and self.state_buff:
                buff = cv2.imread(self.img_buff)
                beau = cv2.imread(self.img_beaut)
                cv2.imwrite(self.img_dst, cv2.addWeighted(buff, 0.5, beau, 0.5, 0))
                self.res_name = self.img_dst
            elif self.state_beauti:
                self.res_name = self.img_beaut
            elif self.state_buff:
                self.res_name = self.img_buff
            else:
                self.res_name = self.img_name
        else:
            self.res_name = self.img_filter[self.select_filter]
        QPm_img = QPixmap(self.res_name)
        self.label_pic.setPixmap(QPm_img)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())
